package com.hjzk.fire;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;
import com.cloudinnov.model.FireCRTEvent;
import com.cloudinnov.utils.FireAlarmServer;
import com.cloudinnov.utils.PropertiesUtils;
import com.cloudinnov.websocket.ControlSolutionDialogueWebsocket;
import com.hjzk.serialport.exception.NoSuchPort;
import com.hjzk.serialport.exception.NotASerialPort;
import com.hjzk.serialport.exception.PortInUse;
import com.hjzk.serialport.exception.SendDataToSerialPortFailure;
import com.hjzk.serialport.exception.SerialPortOutputStreamCloseFailure;
import com.hjzk.serialport.exception.SerialPortParameterFailure;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.ip.tcp.TcpMaster;
import com.serotonin.modbus4j.msg.ModbusRequest;
import com.serotonin.modbus4j.msg.ModbusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import com.serotonin.util.queue.ByteQueue;


public class FireHandler {
	 
	static byte[] rightHandsHead = new byte[15];  ///**右洞手动报警头部  手动报警按钮第16个寄存器异常*/
	static byte[] rightHandsFoot = new byte[22];
	static byte[] leftHands = new byte[36];  //左洞手动报警
	static byte[] rightTempera = new byte[20];  //右洞感温
	static byte[] leftTempera = new byte[20];  //左洞感温
	
	static byte[] mountSmokes = new byte[2];  //山上山下感烟  数组第一位是山上
	static AlarmConfig alarmInfo;
	
	static ModbusFactory modbusFactory;
	private static ModbusRequest rightHandsHeadRequest;
	private static ModbusResponse rightHandsHeadResponse;
	static {
		if (modbusFactory == null) {
			modbusFactory = new ModbusFactory();
		}
	}

	public static WriteRegistersRequest getWriteRegistersRequest(int slaveId,
			int start, short[] values) {
			WriteRegistersRequest request = null;
			try {
				request = new WriteRegistersRequest(slaveId, start, values);
			} catch (ModbusTransportException e) {
				e.printStackTrace();
			}
		return request;
	}

	/**
	 * 得到 WriteRegistersRequest
	 * 
	 * @param ip
	 * @param port
	 * @param slaveId
	 * @param start
	 * @param values
	 */
	public static WriteRegistersResponse getWriteRegistersResponse(
			ModbusMaster tcpMaster, WriteRegistersRequest request) {
		WriteRegistersResponse response = null;
		try {
			response = (WriteRegistersResponse) tcpMaster.send(request);
		} catch (ModbusTransportException e) {
			e.printStackTrace();
		}
		return response;
	}

	/**
	 * 写入
	 * 
	 * @param ip
	 * @param port
	 * @param slaveId
	 * @param start
	 * @param values
	 */
	public static int modbusWTCP(String ip, int port, int slaveId, int start,
			short[] values) {
		ModbusMaster tcpMaster = getTcpMaster(ip, port, slaveId);
		if (tcpMaster == null) {
			System.out.println("tcpMaster is null ");
			return 0;
		}
		tcpMaster = initTcpMaster(tcpMaster);
		WriteRegistersRequest request = getWriteRegistersRequest(slaveId,start, values);

		WriteRegistersResponse response = getWriteRegistersResponse(tcpMaster,request);
		if (response.isException()) {
			return 0;
		} else {
			return 1;
		}
	}

	public static ModbusMaster initTcpMaster(ModbusMaster tcpMaster) {
		if (tcpMaster == null)
			return null;
		try {
			tcpMaster.init();
			return tcpMaster;
		} catch (ModbusInitException e) {
			return null;
		}
	}

	public static ModbusRequest getRequest(int salveId, int start,
			int readLenth, ModbusMaster tcpMaster) {
		ModbusRequest modbusRequest = null;
		try {
			modbusRequest = new ReadHoldingRegistersRequest(salveId, start,readLenth); 
			return modbusRequest;
		} catch (ModbusTransportException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static ModbusResponse getModbusResponse(ModbusMaster tcpMaster,
			ModbusRequest request) {
		ModbusResponse modbusResponse = null;
		try {
			modbusResponse = tcpMaster.send(request);
			return modbusResponse;
		} catch (ModbusTransportException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static ByteQueue modbusRTCP(String ip, int port, int salveId,
			int start, int readLenth) {
		ModbusMaster tcpMaster = getTcpMaster(ip, port, salveId);// 得到tcpMaster
		if (tcpMaster == null) {
			System.out.println("tcpMaster is null ");
			return null;
		}
		return modbusRTCP0(ip, port, salveId, start, readLenth, tcpMaster);
	}

	public static ModbusMaster getTcpMaster(String ip, int port, int salveId) {
		IpParameters params = new IpParameters();
		params.setHost(ip);// 设置ip
		if (port == 0)params.setPort(502);// 设置端口，默认为502
		else params.setPort(port);
		ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, true);// 获取ModbusMaster对象
		return tcpMaster;
	}

	public static ByteQueue modbusRTCP0(String ip, int port, int salveId,
			int start, int readLenth, ModbusMaster tcpMaster) {
		 
		tcpMaster = initTcpMaster(tcpMaster);// 初始化tcpmaster
		ModbusRequest modbusRequest = getRequest(salveId, start, readLenth,tcpMaster);// 得到requst 对象
		ModbusResponse response = getModbusResponse(tcpMaster, modbusRequest);// 发送请求，得到Response

		ByteQueue byteQueue = new ByteQueue(12);
		response.write(byteQueue);
 
		return byteQueue;
	}
	
	public static  byte[] getNowAlaramData(byte[] result,int deviceId,int start, int readLenth,ModbusMaster modbusMaster){
		ModbusRequest request = getRequest(deviceId, start, readLenth,modbusMaster); 
		ModbusResponse modbusResponse = getModbusResponse(modbusMaster, request);
		ByteQueue byteQueue = new ByteQueue(12);
		modbusResponse.write(byteQueue);
		ansisByteQueue(byteQueue, result);
		return result;
	}
	
	static boolean rightHandsFlag=false;
	static boolean leftHandsFlag=false;
	static boolean rightTempFlag=false;
	static boolean leftTempFlag=false;
	static boolean moutainUpFlag=false;
	static boolean moutainDownFlag=false;
	public static  void resetFlag(){
		
		  ScheduledExecutorService service = Executors  
	                .newSingleThreadScheduledExecutor();  
		  service.scheduleWithFixedDelay(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				rightHandsFlag=false;
				leftHandsFlag=false;
				rightTempFlag=false;
				leftTempFlag=false;
				moutainUpFlag=false;
				moutainDownFlag=false;
			}
		}, 0, 5, TimeUnit.MINUTES);
	}
	
	public  void alarmMethod(){
		String ip = PropertiesUtils.findPropertiesKey("nd.fire.detector.ip");
		int port = Integer.parseInt(PropertiesUtils.findPropertiesKey("nd.fire.detector.port"));
		AlarmInfo alarmInfo = new AlarmInfo();
		IpParameters params = new IpParameters();
		params.setPort(port);// 设置端口，默认为502
		params.setHost(ip);// 设置ip
		//ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, true);// 获取ModbusMaster对象
		final ModbusMaster tcpMaster = initTcpMaster(modbusFactory.createTcpMaster(params, true));// 初始化tcpmaster
		 
		  ScheduledExecutorService service = Executors  
	                .newSingleThreadScheduledExecutor();  
	        // 第二个参数为首次执行的延时时间，第三个参数为定时执行的间隔时间  
	        service.scheduleAtFixedRate(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					for (int i = 0; i < 2; i++) {
						 
						byte[] rightHandsHeadData = getNowAlaramData(rightHandsHead, 1, AlarmConfig.rightHandsHead[0],  AlarmConfig.rightHandsHead[1], tcpMaster);
						for (int j = 0; j < rightHandsHeadData.length; j++) {
							if(rightHandsHeadData[j]==1){
								 System.err.println("右洞"+(j+1)+"号手动报警按钮开启");
								 String msg = "右洞"+(j+1)+"号手动报警按钮开启";
								 if(!rightHandsFlag){
									 
									FireCRTEvent fireEvent=new FireCRTEvent();
									fireEvent.setCategoryCode("SDBJAN");
									fireEvent.setDevice("火灾报警器");
									fireEvent.setDeviceId("rightBtn");
									fireEvent.setEvent("手动报警按钮 ");
									fireEvent.setOccurrenceTime(System.currentTimeMillis());
									fireEvent.setPosition(msg);
									fireEvent.setSolutionCode("RDASDF"); 
									Object json = JSON.toJSON(fireEvent);
									FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
									//rightHandsFlag=true;
								 }
							}
						}
						 
						
						byte[] rightHandsFootData = getNowAlaramData(rightHandsFoot, 1, AlarmConfig.rightHandsFoot[0],  AlarmConfig.rightHandsFoot[1], tcpMaster);
						for (int j = 0; j < rightHandsFootData.length; j++) {
							if(rightHandsFootData[j]==1){
								 System.err.println("右洞"+(16+j+1)+"号手动按钮报警");
								 String msg="右洞"+(16+j+1)+"号手动按钮报警";
								 if(!rightHandsFlag){
									 
										FireCRTEvent fireEvent=new FireCRTEvent();
										fireEvent.setCategoryCode("SDBJAN");
										fireEvent.setDevice("火灾报警器");
										fireEvent.setDeviceId("rightBtn");
										fireEvent.setEvent("手动报警按钮 ");
										fireEvent.setOccurrenceTime(System.currentTimeMillis());
										fireEvent.setPosition(msg);
										fireEvent.setSolutionCode("RDASDF"); 
										Object json = JSON.toJSON(fireEvent);
										FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
									    //rightHandsFlag=true;
								 }
							}
						} 
						
						byte[] leftHandsData = getNowAlaramData(leftHands, 1, AlarmConfig.leftHands[0],  AlarmConfig.leftHands[1], tcpMaster);
						for (int j = 0; j < leftHandsData.length; j++) {
							if(leftHandsData[j]==1){
								 System.err.println("左洞"+(40+j)+"号手动按钮报警");
								 
								 String msg="左洞"+(40+j)+"号手动按钮报警";
								 if(!leftHandsFlag){
									 
										FireCRTEvent fireEvent=new FireCRTEvent();
										fireEvent.setCategoryCode("SDBJAN");
										fireEvent.setDevice("火灾报警器");
										fireEvent.setDeviceId("leftBtn");
										fireEvent.setEvent("手动报警按钮 ");
										fireEvent.setOccurrenceTime(System.currentTimeMillis());
										fireEvent.setPosition(msg);
										fireEvent.setSolutionCode("RDASDF"); 
										Object json = JSON.toJSON(fireEvent);
										FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
									    //leftHandsFlag=true;
								 }
							}
						} 

						byte[] rightTemData = getNowAlaramData(rightTempera, 1, AlarmConfig.rightTempture[0],  AlarmConfig.rightTempture[1], tcpMaster);
						for (int j = 0; j < rightTemData.length; j++) {
							if(rightTemData[j]==1){
								 System.err.println("右洞"+(76+j)+"号感温光纤报警");
								 
								 String msg="右洞"+(76+j)+"号感温光纤报警";
								 if(!rightTempFlag){
									 
									FireCRTEvent fireEvent=new FireCRTEvent();
									fireEvent.setCategoryCode("SDBJAN");
									fireEvent.setDevice("火灾报警器");
									fireEvent.setDeviceId("rightTem");
									fireEvent.setEvent("缆式感温设备报警");
									fireEvent.setOccurrenceTime(System.currentTimeMillis());
									fireEvent.setPosition(msg);
									fireEvent.setSolutionCode("RDASDF"); 
									Object json = JSON.toJSON(fireEvent);
									FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
									//rightTempFlag=true;
								 }
							}
						} 
						
						byte[] leftTemData = getNowAlaramData(leftTempera, 1, AlarmConfig.leftTempture[0],  AlarmConfig.leftTempture[1], tcpMaster);
						for (int j = 0; j < leftTemData.length; j++) {
							if(leftTemData[j]==1){
								 System.err.println("左洞"+(96+j)+"号感温光纤报警");
								 
								 String msg="左洞"+(96+j)+"号感温光纤报警";
								 if(!leftTempFlag){
									 
									FireCRTEvent fireEvent=new FireCRTEvent();
									fireEvent.setCategoryCode("SDBJAN");
									fireEvent.setDevice("火灾报警器");
									fireEvent.setDeviceId("leftTem");
									fireEvent.setEvent("缆式感温设备报警");
									fireEvent.setOccurrenceTime(System.currentTimeMillis());
									fireEvent.setPosition(msg);
									fireEvent.setSolutionCode("RDASDF"); 
									Object json = JSON.toJSON(fireEvent);
									FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
									//leftTempFlag=true;
								 }
							}
						} 
						
						byte[] mountainData = getNowAlaramData(mountSmokes, 1,AlarmConfig.mountSmoke[0], AlarmConfig.mountSmoke[1], tcpMaster);
						for (int j = 0; j < mountainData.length; j++) {
							if(mountainData[j]==1){
								if(j==0&&mountainData[j]==1){
									 System.err.println("山上点型感烟装置报警开启");
									 
									 String msg="山上点型感烟装置报警开启";
									 if(!moutainUpFlag){
										 
										FireCRTEvent fireEvent=new FireCRTEvent();
										fireEvent.setCategoryCode("SDBJAN");
										fireEvent.setDevice("火灾报警器");
										fireEvent.setDeviceId("headMount");
										fireEvent.setEvent("点型感烟设备报警");
										fireEvent.setOccurrenceTime(System.currentTimeMillis());
										fireEvent.setPosition(msg);
										fireEvent.setSolutionCode("RDASDF"); 
										Object json = JSON.toJSON(fireEvent);
										FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
										///moutainUpFlag=true;
										 
									 }
									 
								}else if(j==1&&mountainData[j]==1){
									System.err.println("山下点型感烟装置报警开启");
									
									 String msg="山下点型感烟装置报警开启";
									 if(!moutainDownFlag){
										  
										FireCRTEvent fireEvent=new FireCRTEvent();
										fireEvent.setCategoryCode("SDBJAN");
										fireEvent.setDevice("火灾报警器");
										fireEvent.setDeviceId("footMount");
										fireEvent.setEvent("点型感烟设备报警");
										fireEvent.setOccurrenceTime(System.currentTimeMillis());
										fireEvent.setPosition(msg);
										fireEvent.setSolutionCode("RDASDF"); 
										Object json = JSON.toJSON(fireEvent);
										FireAlarmServer.fireTemplate.convertAndSend(JSON.toJSONString(json));
										//moutainDownFlag=true;
									 }
									 
								}
							}
						}
					}
				}
			}, 0, 50, TimeUnit.SECONDS);  
		 
		 
	}
	
	public static void startAlarm(){
		
		try {
			FireOrder.startAlarm();
		} catch (SendDataToSerialPortFailure | SerialPortOutputStreamCloseFailure | SerialPortParameterFailure
				| NotASerialPort | NoSuchPort | PortInUse | InterruptedException e) {
			// TODO Auto-generated catch block
			System.err.println("报警设备异常");
		}
	}
 
	 public static void SendMsg2Socket(String msg){
		 Iterator<Map.Entry<String, ControlSolutionDialogueWebsocket>> controlSolutionDialogueWebsocket = ControlSolutionDialogueWebsocket.webSocketMap
					.entrySet().iterator();
			while (controlSolutionDialogueWebsocket.hasNext()) {
				Map.Entry<String, ControlSolutionDialogueWebsocket> controlSolutionDialogueEntry = controlSolutionDialogueWebsocket
						.next();
				try {
					controlSolutionDialogueEntry.getValue().sendMessage(msg);
				} catch (IOException e) {
				}
			}
	 }
	
	
	public static void main(String[] args) throws InterruptedException {
		 
		 FireHandler fireHandler=new FireHandler();
		 fireHandler.alarmMethod();
		 
	}
	
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}
 
	public static boolean ansisByteQueue(ByteQueue bq,byte[] dataBytes) {
		byte[] result = bq.peekAll();
		byte[] temp = null;
		ByteBuffer buffer = ByteBuffer.wrap(result, 3, result.length - 3);//直接获取 data
		int i=0;
		while (buffer.hasRemaining()) {
			temp = new byte[2];
			buffer.get(temp, 0, temp.length);
			 
			int data = Integer.parseInt(bytesToHexString(temp), 16);
			dataBytes[i++]=(byte) data;
		}
		return true;

	}
	
	/**
	 * 右洞手动报警
	 * @throws InterruptedException 
	 */
	public static AlarmInfo getRightHandsAlarm() throws InterruptedException{
		AlarmInfo alarmInfo=new AlarmInfo();
		int count=0;
		ByteQueue rightHandsHeadBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.rightHandsHead[0], AlarmConfig.rightHandsHead[1]);
		 if(ansisByteQueue(rightHandsHeadBQ,rightHandsHead)){
			 for (int i = 0; i < rightHandsHead.length; i++) {
				 if(rightHandsHead[i]==1){
					 count++;
					 alarmInfo.oneCodeList.add(i+1);
				 } 
			}
		 }
		  
		 ByteQueue rightHandsFootBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.rightHandsFoot[0], AlarmConfig.rightHandsFoot[1]);
		 if(ansisByteQueue(rightHandsFootBQ,rightHandsFoot)){
			 for (int i = 0; i < rightHandsFoot.length; i++) {
				 if(rightHandsFoot[i]==1){
					 count++;
					 alarmInfo.oneCodeList.add(16+i+1);
				 } 
			}
		 }
		 if(count>0){
			 alarmInfo.setAlarm(true);
		 }
		 return alarmInfo;
	}
	
	/**
	 * 左洞手动报警
	 */
	public static AlarmInfo getLeftHandsAlarm(){
		AlarmInfo alarmInfo=new AlarmInfo();
		int count=0;
		 ByteQueue leftHandsBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.leftHands[0], AlarmConfig.leftHands[1]);
		 if(ansisByteQueue(leftHandsBQ,leftHands)){
			 for (int i = 0; i < leftHands.length; i++) {
				 if(leftHands[i]==1){
					 count++;
					 alarmInfo.oneCodeList.add(40+i);
				 } 
			}
		 }
		 if(count>0){
			 
			 alarmInfo.setAlarm(true);
		 }
		 return alarmInfo;
	}
	
	/**
	 * 右洞感温装置报警
	 */
	public static AlarmInfo getRightTemptureAlarm(){
		AlarmInfo alarmInfo=new AlarmInfo();
		int count=0;
		ByteQueue rightTepmperaBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.rightTempture[0], AlarmConfig.rightTempture[1]);
		 if(ansisByteQueue(rightTepmperaBQ,rightTempera)){
			 for (int i = 0; i < rightTempera.length; i++) {
				 if(rightTempera[i]==1){
					 count++;
					 alarmInfo.oneCodeList.add(76+i);
				 }
			}
			 if(count>0){
				 alarmInfo.setAlarm(true);
			 }
		 }
		 return alarmInfo;
	}
	
	/**
	 * 左洞感温装置报警
	 */
	public static AlarmInfo getLeftTemptureAlarm(){
		 AlarmInfo alarmInfo=new AlarmInfo();
		 int count=0;
		 ByteQueue leftTepmperaBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.leftTempture[0], AlarmConfig.leftTempture[1]);
		 if(ansisByteQueue(leftTepmperaBQ,leftTempera)){
			 for (int i = 0; i < leftTempera.length; i++) {
				 if(leftTempera[i]==1){
					 count++;
					 alarmInfo.oneCodeList.add(96+i);
				 }
			}
			 if(count>0){
				 alarmInfo.setAlarm(true);
			 }
		 }
		 return alarmInfo;
	}
	
	/**
	 * 山上山下感烟装置
	 */
	public static AlarmInfo getMountSmokeAlarm(){
		AlarmInfo alarmInfo=new AlarmInfo();
		int count=0;
		ByteQueue mountSmokeBQ = FireHandler.modbusRTCP(AlarmConfig.ip, AlarmConfig.port, AlarmConfig.deviceId,AlarmConfig.mountSmoke[0], AlarmConfig.mountSmoke[1]);
		if(ansisByteQueue(mountSmokeBQ,mountSmokes)){
			 for (int i = 0; i < mountSmokes.length; i++) {
				 if(mountSmokes[0]==1){
					
					 count++;
					 alarmInfo.oneCodeList.add(116);
				 }else if(mountSmokes[1]==1){
					 
					 count++;
					 alarmInfo.oneCodeList.add(117);
				 }
			}
			 if(count>0){
				 alarmInfo.setAlarm(true);
			 }
		 }
		return alarmInfo;
	}

}
